﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using System.Data.SQLite;

namespace Pool.DataBase.DAL
{
    public class NHibernateDAL : IDAL
    {
        private const string CONNECTION_STRING_FORMAT = "Data Source={0}db\\Pool.db;Version=3";
        private static Configuration s_NHibernateConfiguration = (new Configuration()).Configure(
            AppDomain.CurrentDomain.BaseDirectory + "hibernate.cfg.xml");
        private ITransaction m_trans = null;

        private ISession m_Session = null;
        protected ISession Session
        {
            get
            {
                if (null == m_Session)
                {
                    s_NHibernateConfiguration.DataBaseIntegration(db => db.ConnectionString = string.Format(CONNECTION_STRING_FORMAT, AppDomain.CurrentDomain.BaseDirectory));
                    ISessionFactory factory = s_NHibernateConfiguration.BuildSessionFactory();
                    m_Session = factory.OpenSession();
                   
                }
                return m_Session;
            }
        }

        public T GetById<T>(object id)
        {
            return Session.Get<T>(id);
        }

        public IList<T> GetAll<T>() where T : class
        {
            return QueryOver<T>();
        }

        public IList<T> GetAll<T>(int pageIndex, int pageSize) where T : class
        {
            return QueryOver<T>(pageIndex: pageIndex, pageSize: pageSize);
        }

        internal IList<T> QueryOver<T>(
           Expression<Func<T, bool>> where = null,
           ICriterion criteria = null,
           Int32 pageIndex = 1,
           Int32 pageSize = 0) where T : class
        {
            var query = Session.QueryOver<T>();
            if (null != where)
                query = query.Where(where);
            if (null != criteria)
                query = query.Where(criteria);
            if (0 < pageSize)
            {
                if (1 < pageIndex)
                    return query.Skip((pageIndex - 1) * pageSize).Take(pageSize).List();
                else
                    return query.Take(pageSize).List();
            }
            return query.List();
        }

        public void Add(object item)
        {
            Session.Save(item);
        }

        public void Update(object item)
        {
            Session.Merge(item);
        }

        public void Delete(object item)
        {
            Session.Delete(item);
        }

        public void BeginTransaction()
        {
            m_trans = Session.BeginTransaction();
        }

        public void Commit()
        {
            m_trans.Commit();
            m_trans.Dispose();
            m_trans = null;
        }

        public void Rollback()
        {
            m_trans.Rollback();
            m_trans.Dispose();
            m_trans = null;
        }
    }
}
